package com.sumainfor.common.utlis;


import com.sumainfor.common.config.GenerateUUID;
import com.sumainfor.common.config.LockUtil;
import com.sumainfor.common.util.CustomMap;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 功能描述:
 * 自定义UUID
 *
 * @Author zhlu
 * @Description //TODO
 * @Date 2019/3/12 15:40
 */
public class ComUtils {


    @Autowired
    private GenerateUUID generateUUID;

    @Autowired
    private LockUtil lockUtil;

    public static Map<String, String> unicodeParamstr2Map(String str) {
        String paramstr = StringEscapeUtils.unescapeJava(str);
        Map<String, String> result = new LinkedHashMap<String, String>();
        String[] pairs = paramstr.split("&");
        for (String pair : pairs) {
            int idx = pair.indexOf("=");
            if (idx >= 0) {
                result.put(pair.substring(0, idx), pair.substring(idx + 1));
            } else {
                result.put(pair, null);
            }
        }
        return result;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    public static ArrayList randomList(ArrayList<Map<String, Object>> sourceList) {
        if (isEmpty(sourceList)) {
            return sourceList;
        }
        ArrayList randomList = new ArrayList(sourceList.size());
        do {
            int randomIndex = Math.abs(new Random().nextInt(sourceList.size()));
            randomList.add(sourceList.remove(randomIndex));
        } while (sourceList.size() > 0);
        return randomList;
    }

    /**
     * 随机指定范围内N个不重复的数
     * 最简单最基本的方法
     *
     * @param min 指定范围最小值
     * @param max 指定范围最大值
     * @param n   随机数个数
     */
    public static int[] randomCommon(int min, int max, int n) {
        if (n > (max - min + 1) || max < min) {
            return null;
        }
        int[] result = new int[n];
        int count = 0;
        while (count < n) {
            int num = (int) (Math.random() * (max - min)) + min;
            boolean flag = true;
            for (int j = 0; j < n; j++) {
                if (num == result[j]) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                result[count] = num;
                count++;
            }
        }
        return result;
    }

    @SuppressWarnings("rawtypes")
    public static boolean isEmpty(ArrayList sourceList) {
        return (sourceList == null || sourceList.size() == 0);
    }

    public static UUID byte2uuid(byte[] bytes) {
        ByteBuffer bb = ByteBuffer.wrap(bytes);
        long firstLong = bb.getLong();
        long secondLong = bb.getLong();
        return new UUID(firstLong, secondLong);

    }

    public static byte[] uuid2byte(UUID uuid) {
        ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
        bb.putLong(uuid.getMostSignificantBits());
        bb.putLong(uuid.getLeastSignificantBits());
        return bb.array();
    }

    public static UUID hexstr2uuid(String hexstr) {
        // Use regex to format the hex string by inserting hyphens in the canonical format: 8-4-4-4-12
        if (StringUtils.isEmpty(hexstr)) {
            return null;
        }
        String hexStringWithInsertedHyphens = hexstr.replaceFirst("([0-9a-fA-F]{8})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]+)", "$1-$2-$3-$4-$5");
        java.util.UUID uuid = java.util.UUID.fromString(hexStringWithInsertedHyphens);
        return uuid;
    }

    public static String hexstr2str(String hexstr) {
        // Use regex to format the hex string by inserting hyphens in the canonical format: 8-4-4-4-12
        if (StringUtils.isEmpty(hexstr)) {
            return null;
        }
        String hexStringWithInsertedHyphens = hexstr.replaceFirst("([0-9a-fA-F]{8})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]+)", "$1-$2-$3-$4-$5");
        return hexStringWithInsertedHyphens;
    }

    public static String randomUID() {
        return randomUID("");
    }

    public static String randomUID(String prefix) {
        int length = 32;
        String prefixStr = "";
        if (prefix == null || "".equals(prefix)) {
            prefixStr = "";
        } else {
            length = length - prefix.length() - 1;
            prefixStr = prefix.toUpperCase() + "_";
        }

        String uuid = prefixStr + RandomStringUtils.random(length, "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890");
        return uuid;
    }

    public static String randomAlphanumUID() {
        return randomAlphanumUID("");
    }

    public static String randomAlphanumUID(String prefix) {
        int length = 32;
        String prefixStr = "";
        if (prefix == null || "".equals(prefix)) {
            prefixStr = "";
        } else {
            length = length - prefix.length() - 1;
            prefixStr = prefix.toUpperCase() + "_";
        }
        String uuid = prefixStr + RandomStringUtils.random(length, "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890");
        return uuid;
    }

    public static String randomNumUID() {
        int length = 8;
        String prefixStr = "";
        String uuid = prefixStr + RandomStringUtils.random(length, "ABCD1234567890");
        return uuid;
    }

    private static int sequence = 0;

    private static int length = 4;

    /**
     * 获取根据传入的编码得到“编码-YYYYMMDD+4位自增长码(15位)”的编号
     * prefix：前缀
     * UUID：今天最大值
     *
     * @return
     */
    public static synchronized String getLocalTrmSeqNum(String prefix, int UUID) {
        int num = 0;
        if (UUID == 0) {
            num = sequence >= 9999 ? 1 : sequence + 1;
        } else {
            num = UUID >= 9999 ? 1 : UUID + 1;
        }
        String datetime = new SimpleDateFormat("yyyyMMdd")
                .format(new Date());
        String s = Integer.toString(num);
        return prefix.toUpperCase() + "-" + datetime + addLeftZero(s, length);
    }

    /**
     * 自动查询 获取UUID
     * 带锁的方法
     *
     * @param prefix
     * @param dataBase
     * @param tableName
     * @param uuidFieldName
     * @return
     */
    public String getLocalTrmSeqNumByLook(String prefix, String dataBase, String tableName, String uuidFieldName) {
        try {
            lockUtil.getUntilHaveLock(tableName);
            Map<String, Object> map = generateUUID.getUuid(CustomMap.create("uuid", uuidFieldName)
                    .put("database", dataBase)
                    .put("surface", tableName)
            );
            if (map == null) {
                return ComUtils.getLocalTrmSeqNum(prefix, 0);
            } else {
                return ComUtils.getLocalTrmSeqNum(prefix, MapUtils.getIntValue(map, "uuid"));
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lockUtil.unLock(tableName);
        }
        return null;
    }

    /**
     * 左填0
     *
     * @param s
     * @param length
     * @return
     */
    public static String addLeftZero(String s, int length) {
        // StringBuilder sb=new StringBuilder();
        int old = s.length();
        if (length > old) {
            char[] c = new char[length];
            char[] x = s.toCharArray();
            if (x.length > length) {
                throw new IllegalArgumentException(
                        "Numeric value is larger than intended length: " + s
                                + " LEN " + length);
            }
            int lim = c.length - x.length;
            for (int i = 0; i < lim; i++) {
                c[i] = '0';
            }
            System.arraycopy(x, 0, c, lim, x.length);
            return new String(c);
        }
        return s.substring(0, length);

    }

    public static void main(String[] args) {
        System.err.println(randomUID());
    }
}
